package com.xcity.game.equip;

import java.util.ArrayList;
import java.util.List;

import org.slf4j.Logger;

import com.alibaba.fastjson.annotation.JSONField;
import com.xcity.db.entity.Employee;
import com.xcity.game.combat.attr.CombatAttribute;
import com.xcity.game.combat.attr.CombatAttributeType;
import com.xcity.game.equip.template.EquipBaseTemplate;
import com.xcity.game.equip.template.EquipDataTemplate;
import com.xcity.pomelo.push.SyncPush;
import com.xcity.pomelo.push.sync.CustomSync;
import com.xcity.util.IdUtils;

import naga.x.App;
import naga.x.game.template.TemplateService;
import naga.x.game.time.TimeUpdater;

public class Equip {

	@JSONField(name = "0")
	protected int templateId; // 基础模板
	@JSONField(name = "1")
	protected int dataTemplateId; // 数值模板
	@JSONField(name = "2")
	protected long id;
	@JSONField(name = "3")
	protected int level;
	@JSONField(name = "4")
	protected int exp;
	@JSONField(name = "5")
	protected List<CombatAttribute> attrs;
	@JSONField(name = "6")
	protected State state = State.IN_BAG;
	@JSONField(name = "7")
	protected long createTime;
	
	public static enum State {
		IN_BAG, IN_EMPLOYEE
	}
	
	protected Equipments vm;
	protected EquipBaseTemplate template;
	protected EquipDataTemplate dataTemplate;
	protected static final Logger LOG = EquipmentService.LOG;
	
	public Equip() {}
	
	public Equip(EquipBaseTemplate template, EquipDataTemplate dataTemplate, List<CombatAttribute> attrs) {
		this.id = IdUtils.nextEquipmentId();
		this.templateId = template.getId();
		this.template = template;
		this.dataTemplateId = dataTemplate.getId();
		this.dataTemplate = dataTemplate;
		this.level = 0;
		this.exp = 0;
		this.attrs = attrs;
		this.createTime = TimeUpdater.getInstance().now();
	}

	public int getTemplateId() {
		return templateId;
	}

	public void setTemplateId(int templateId) {
		this.templateId = templateId;
	}
	
	public int getDataTemplateId() {
		return dataTemplateId;
	}

	public void setDataTemplateId(int dataTemplateId) {
		this.dataTemplateId = dataTemplateId;
	}

	@JSONField(serialize = false)
	public EquipBaseTemplate getTemplate() {
		return template != null ? template : (template = App.getApp().getServiceManager().get(TemplateService.class).get(EquipBaseTemplate.class, templateId));
	}
	
	@JSONField(serialize = false)
	public EquipDataTemplate getDataTemplate() {
		return dataTemplate != null ? dataTemplate : (dataTemplate = App.getApp().getServiceManager().get(TemplateService.class).get(EquipDataTemplate.class, dataTemplateId));
	}

	public long getId() {
		return id;
	}

	public void setId(long id) {
		this.id = id;
	}

	public int getLevel() {
		return level;
	}

	public void setLevel(int level) {
		this.level = level;
	}

	public int getExp() {
		return exp;
	}

	public void setExp(int exp) {
		this.exp = exp;
	}

	public List<CombatAttribute> getAttrs() {
		return attrs;
	}

	public void setAttrs(List<CombatAttribute> attrs) {
		this.attrs = attrs;
	}

	public State getState() {
		return state;
	}

	public void setState(State state) {
		this.state = state;
	}
	
	public void setState(State state, boolean sync) {
		this.state = state;
		if (sync) {
			// 同步给客户端
			switch (state) {
				case IN_BAG:
					vm.equipAdded(this);
					break;
				case IN_EMPLOYEE:
					vm.equipRemoved(this);
					break;
			}
		}
	}
	
	public long getCreateTime() {
		return createTime;
	}

	public void setCreateTime(long createTime) {
		this.createTime = createTime;
	}
	
	@JSONField(serialize = false)
	public EquipQuality getQuality() {
		return getDataTemplate().getQuality();
	}
	
	@JSONField(serialize = false)
	public EquipPosition getPos() {
		return getTemplate().getPos();
	}
	
	@JSONField(serialize = false)
	public EquipBrand getBrand() {
		return getTemplate().getBrand();
	}
	
	public float getAttributeValue(CombatAttributeType type) {
		List<CombatAttribute> attrs = this.attrs;
		for (int i = 0; i < attrs.size(); i++) {
			CombatAttribute attr = attrs.get(i);
			if (attr.getType() == type) {
				return attr.getValue();
			}
		}
		return 0f;
	}
	
	@JSONField(serialize = false)
	public boolean isEmpty() {
		return id == 0;
	}

	public boolean addExp(int val, String cause) {
		if (val <= 0 || level >= EquipUtils.MAX_LEVEL) {
			return false;
		}
		int oldExp = exp;
		exp += val;
		EquipQuality quality = getDataTemplate().getQuality();
		int newLvl = EquipUtils.exp2Lvl(quality, exp, level);
		if (newLvl > level) {
			// 主属性、物防、法防成长
			int delta = newLvl - level;
			float factor = (float) Math.pow(EquipUtils.ATTR_GROWTH_FACTOR, delta);
			int mask = EquipUtils.doLevelUp(attrs, factor);
			level = newLvl;
			// 同步穿戴该装备的员工的属性
			Employee wearer = EquipUtils.getWearer(this);
			if (wearer != null) {
				wearer.fireAttributesChanged(mask);
			}
		}
		vm.getOwner().send(new CustomSync(SyncPush.SYNC_EQUIP_ATTRS, new SimpleAttr(this)));
		LOG.info("[EQUIP ADDEXP]ID[{}]EQUIP[{}]TID[{}]DTID[{}]OLD[{}]NEW[{}]LVL[{}]CAUSE[{}]", vm.getOwner().getId(), id, getTemplateId(), getDataTemplateId(), oldExp, exp, level, cause);
		return true;
	}
	
	@JSONField(serialize = false)
	public Equipments getVm() {
		return vm;
	}
	
	static class SimpleAttr {
		protected int level;
		protected int exp, exp0;
		protected int maxExp;
		protected List<com.xcity.pomelo.response.EquipmentBagResponse.CombatAttribute> attrs;
		public SimpleAttr(Equip ref) {
			this.level = ref.getLevel();
			EquipQuality quality = ref.getDataTemplate().getQuality();
			this.exp = EquipUtils.getCurrentExp(quality, ref.getExp(), level);
			this.exp0 = ref.getExp();
			this.maxExp = EquipUtils.getNextLvlNeedExp(quality, level);
			this.attrs = new ArrayList<>(ref.getAttrs().size());
			for (int i = 0; i < ref.getAttrs().size(); i++) {
				this.attrs.add(new com.xcity.pomelo.response.EquipmentBagResponse.CombatAttribute(ref.getAttrs().get(i)));
			}
		}
		public int getLevel() {
			return level;
		}
		public void setLevel(int level) {
			this.level = level;
		}
		public int getExp() {
			return exp;
		}
		public void setExp(int exp) {
			this.exp = exp;
		}
		public int getExp0() {
			return exp0;
		}
		public void setExp0(int exp0) {
			this.exp0 = exp0;
		}
		public int getMaxExp() {
			return maxExp;
		}
		public void setMaxExp(int maxExp) {
			this.maxExp = maxExp;
		}
		public List<com.xcity.pomelo.response.EquipmentBagResponse.CombatAttribute> getAttrs() {
			return attrs;
		}
		public void setAttrs(List<com.xcity.pomelo.response.EquipmentBagResponse.CombatAttribute> attrs) {
			this.attrs = attrs;
		}
	}

}
